/**
 * Framework background class
 * @constructor
 */
function Framework(_options){
	this.className = '[Add-on framework object]';
	var self = this,
		button = new FrameworkButton(this),
		id = null,
		fnCallbacks = {
			BeforeNavigate: [],
			DocumentComplete: [],
			TabChanged: []
		},
		options = $.extend({
		
		}, _options),
		console = Components.classes['@mozilla.org/consoleservice;1']['getService'](Components.interfaces.nsIConsoleService),
		prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
									['getService'](Components.interfaces.nsIPrefService)
									['getBranch']("extensions.skydns."),
		progressListener = {
			'init': function() { 
			  gBrowser.browsers.forEach(function (browser) {  
				this._toggleProgressListener(browser['webProgress'], true);  
			  }, this);  
			  gBrowser.tabContainer.addEventListener("TabOpen", this, false);  
			  gBrowser.tabContainer.addEventListener("TabClose", this, false);  
			},  
			'uninit': function() {  
			  gBrowser.browsers.forEach(function (browser) {  
				this ._toggleProgressListener(browser['webProgress'], false);  
			  }, this);  
			  gBrowser.tabContainer.removeEventListener("TabOpen", this, false);  
			  gBrowser.tabContainer.removeEventListener("TabClose", this, false);  
			},  
			'handleEvent': function(aEvent) {  
			  var tab = aEvent['target'],
					webProgress = gBrowser.getBrowserForTab(tab)['webProgress'];  
			  this._toggleProgressListener(webProgress, ("TabOpen" == aEvent['type']));  
			},  
			_toggleProgressListener : function(aWebProgress, aIsAdd) {  
			  if (aIsAdd) {  
				aWebProgress['addProgressListener'](this, aWebProgress['NOTIFY_ALL'] );  
			  } else {  
				aWebProgress['removeProgressListener'](this);  
			  }  
			},
			'QueryInterface': function(aIID){
				if (aIID['equals'](Components.interfaces.nsIWebProgressListener) ||
					aIID['equals'](Components.interfaces.nsISupportsWeakReference) ||
					aIID['equals'](Components.interfaces.nsISupports)){
					return this;
				}
				throw Components['results']['S_NOINTERFACE'];
			},
			'onProgressChange': function (aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {},
			'onStatusChange': function(aWebProgress, aRequest, aStatus, aMessage) {},
			'onSecurityChange': function(aWebProgress, aRequest, aState) {},
			'onLinkIconAvailable': function(a) {},
			'onStateChange': function (aWebProgress, aRequest, aStateFlags, aStatus){
					if ((aStateFlags &  Components.interfaces.nsIWebProgressListener['STATE_START']) &&
							(aStateFlags &  Components.interfaces.nsIWebProgressListener['STATE_IS_DOCUMENT']) &&
							(aStateFlags &  Components.interfaces.nsIWebProgressListener['STATE_IS_NETWORK'])){
						var aBrowser = this.getBrowser(aWebProgress),
							aUri = aRequest['QueryInterface'](Components.interfaces.nsIChannel)['URI'],
							bAbort = false;
							self.log('bn', aBrowser);
						if(aUri['schemeIs']("http") || aUri['schemeIs']("https")){
							log(aUri.host)
							$.each(fnCallbacks.BeforeNavigate, function(i, callback){
								bAbort = callback(aUri, aBrowser) || bAbort;
							});
							if (bAbort){
								aRequest.cancel(Components.results.NS_BINDING_ABORTED);
								log('canceled');
							}
						}
					}
				
			},
			'onLocationChange': function(aProgress, aRequest, aLocation) {},
			getBrowser: function (aWebProgress) {
				return gBrowser.getBrowserForDocument(aWebProgress['DOMWindow']['top']['document']);
			}
		},
		appcontent = document.getElementById("appcontent");   // browser  

	progressListener['init']();
	if(appcontent) { 
		appcontent.addEventListener("DOMContentLoaded", function(aEvent){
			var doc = aEvent['originalTarget'],
				url = doc['location']?doc['location']['href']:'';
			if(doc['nodeName'] == "#document" && url && url.indexOf("http")==0){
				var	aBrowser = gBrowser.getBrowserForDocument(doc),
					aUri = aBrowser?aBrowser.currentURI:null;
				$.each(fnCallbacks.DocumentComplete, function(i, callback){
					callback(aUri, aBrowser);
				});	
			}
		}, false); 
	}
	gBrowser.tabContainer.addEventListener("TabSelect", function(aEvent){
		var aBrowser = gBrowser.selectedBrowser,
			aUri = aBrowser.currentURI;
		$.each(fnCallbacks.TabChanged, function(i, callback){
			callback(aUri, aBrowser);
		});	
	}, false);

	
	
	this['onBeforeNavigate'] = function(fnCallback){
		fnCallbacks.BeforeNavigate.push(fnCallback);
	};
	
	this['onDocumentComplete'] = function(fnCallback){
		fnCallbacks.DocumentComplete.push(fnCallback);
	};
	
	this['onTabChanged'] = function(fnCallback){
		fnCallbacks.TabChanged.push(fnCallback);
	};

	function navigate(param){
		if (param['url'].indexOf("http")!=0){
			param['url'] = "chrome://skydns/content/" + param['url'];
		}
		if(param['newtab']){
			gBrowser['selectedTab'] = gBrowser.addTab(param['url']);
		} else {
			if(param['tab']){
				param['tab']['stop']();
				param['tab']['loadURIWithFlags'](param['url'], 64, null, null, null);
			} else {
				gBrowser.selectedBrowser['webNavigation']['stop'](3);
				gBrowser.selectedBrowser['loadURI'](param['url'], null, null);
			}
		}
		if(param['callback'])
			param['callback']();
	};

	function log(){
		console['logStringMessage']($.map(arguments, function(arg){return arg}).join("\n--------------------------\n"));
	}
	
	function getItem(id){
		switch (prefBranch['getPrefType'](id))
		{
			case prefBranch['PREF_STRING']:
				return prefBranch['getComplexValue'](id, Components.interfaces.nsISupportsString)['data'];
			case prefBranch['PREF_INT']:
				return prefBranch['getIntPref'](id);
			case prefBranch.PREF_BOOL:
				return prefBranch['getBoolPref'](id);
			default:
				return null;
		}
	}	
	
	function setItem(id, val){
		if (typeof(val) == "number"){
			prefBranch['setIntPref'](id, val);
		} else if (typeof val == "string"){
			var str = Components.classes["@mozilla.org/supports-string;1"]
						['createInstance'](Components.interfaces.nsISupportsString);
			str['data'] = val;
			prefBranch['setComplexValue'](id, Components.interfaces.nsISupportsString, str);
		} else if (typeof val == "boolean"){
			prefBranch['setBoolPref'](id, val);
		}
	}
	
	function setButton(prop){
		button.set(prop);
	}
	
	this['navigate'] = navigate;
	this['log'] = log;
	this['setItem'] = setItem;
	this['getItem'] = getItem;
	this['setButton'] = button.set;
	
	id = getItem('id');
	if(!id){
		id = $['uuid']().toString();
		setItem('id', id);
		if(options['urlAfterInstall']){
			navigate({
				'url': options['urlAfterInstall'],
				'newtab': true
			})
		}
	}
}
this['Framework'] = Framework;



/**
 * FrameworkButton background class
 * @constructor
 */
function FrameworkButton(_tool){
	this.className = '[Add-on framework button]';
	var self = this,
		tool = _tool,
		button = document.getElementById("skydns-toolbar-button"),
		defaultData = {
			'title': button.getAttribute('tooltiptext'),
			'icon': button.getAttribute('image')
		},
		progressListener = {
			'init': function() { 
			  gBrowser.browsers.forEach(function (browser) {  
				this._toggleProgressListener(browser['webProgress'], true);  
			  }, this);  
			  gBrowser.tabContainer.addEventListener("TabOpen", this, false);  
			  gBrowser.tabContainer.addEventListener("TabClose", this, false);  
			},  
			'uninit': function() {  
			  gBrowser.browsers.forEach(function (browser) {  
				this ._toggleProgressListener(browser['webProgress'], false);  
			  }, this);  
			  gBrowser.tabContainer.removeEventListener("TabOpen", this, false);  
			  gBrowser.tabContainer.removeEventListener("TabClose", this, false);  
			},  
			'handleEvent': function(aEvent) {  
			  var tab = aEvent['target'],
					webProgress = gBrowser.getBrowserForTab(tab)['webProgress'];  
			  this._toggleProgressListener(webProgress, ("TabOpen" == aEvent['type']));  
			},  
			_toggleProgressListener : function(aWebProgress, aIsAdd) {  
			  if (aIsAdd) {  
				aWebProgress['addProgressListener'](this, aWebProgress['NOTIFY_ALL'] );  
			  } else {  
				aWebProgress['removeProgressListener'](this);  
			  }  
			},
			'QueryInterface': function(aIID){
				if (aIID['equals'](Components.interfaces.nsIWebProgressListener) ||
					aIID['equals'](Components.interfaces.nsISupportsWeakReference) ||
					aIID['equals'](Components.interfaces.nsISupports)){
					return this;
				}
				throw Components['results']['S_NOINTERFACE'];
			},
			'onProgressChange': function (aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {},
			'onStatusChange': function(aWebProgress, aRequest, aStatus, aMessage) {},
			'onSecurityChange': function(aWebProgress, aRequest, aState) {},
			'onLinkIconAvailable': function(a) {},
			'onStateChange': function (aWebProgress, aRequest, aStateFlags, aStatus){
					if ((aStateFlags &  Components.interfaces.nsIWebProgressListener['STATE_STOP']) &&
							(aStateFlags &  Components.interfaces.nsIWebProgressListener['STATE_IS_DOCUMENT'])){
						var aBrowser = this.getBrowser(aWebProgress),
							aUri = aRequest['QueryInterface'](Components.interfaces.nsIChannel)['URI'];
							if(bActive && aUri['spec'].indexOf("content/block.html#")<0){
								tool.log(aUri['spec']);
								aBrowser.setUserData('frameworkButton', null, null);
								set($.extend({}, defaultData, {'tab': aBrowser}), true);
							} 
					}
				
			},
			'onLocationChange': function(aProgress, aRequest, aLocation) {},
			getBrowser: function (aWebProgress) {
				return gBrowser.getBrowserForDocument(aWebProgress['DOMWindow']['top']['document']);
			}
		},
		appcontent = document.getElementById("appcontent");   // browser  
		bActive = false;
	
	progressListener['init']();
	
	gBrowser.tabContainer.addEventListener("TabSelect", function(aEvent){
		if(bActive){
			var aBrowser = gBrowser.getBrowserForTab(aEvent.target);
			set($.extend({}, aBrowser.getUserData('frameworkButton')?
						aBrowser.getUserData('frameworkButton'):defaultData, {'tab': aBrowser}), true);
		}
	}, true);
	
	gBrowser.tabContainer.addEventListener("TabClose", function(aEvent){
		if(bActive){
			var aBrowser = gBrowser.getBrowserForTab(aEvent.target);
			if(aBrowser.getUserData('frameworkButton')){
				aBrowser.setUserData('frameworkButton', null, null);
			}
		}
	}, true);
	
	function set(prop, change){
		if(!prop['tab'] || (prop['tab'] == gBrowser.getBrowserForTab(gBrowser['selectedTab']))){
			if(prop['icon'])
				button.setAttribute('image', (prop['icon'].indexOf("http")&&prop['icon'].indexOf("chrome"))?("chrome://skydns/content/"+prop['icon']):prop['icon']);
			if(prop['title'])
				button.setAttribute('tooltiptext', prop['title']);
		}
		if(!change){
			if(prop['tab']){
				var tab = prop['tab'];
				prop['tab'] = null;
				tab.setUserData('frameworkButton', prop, null);
				bActive = true;
			} else {
				defaultData = prop;
				var num = gBrowser.browsers.length;
				for (var i = 0; i < num; i++) {
					var b = gBrowser.getBrowserAtIndex(i);
					b.setUserData('frameworkButton', null, null);
				}
				bActive = false;
			}
		}
	}

	this['set'] = set;
}

